package com.key.puzzlemodel.mvvm

import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.WindowManager
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type


/**
 *
 */
abstract class BaseMVVMActivity<VDB : ViewDataBinding, VM : ViewModel>(useDataBinding: Boolean = true) : AppCompatActivity() {

    lateinit var mVDB: VDB // 视图数据绑定
    lateinit var mVM: VM // ViewModel

    abstract val layoutId: Int? // xml布局文件，子类指定
    private val _useBinding = useDataBinding

    /**
     * UI初始化，[子类必须实现]
     * 会在onCreate方法中获取DataBinding和ViewModel之后被调用
     */
    protected abstract fun initView(savedInstanceState: Bundle?)

    /**
     * 绑定监听事件
     */
    open fun bindEvent() {}

    /**
     * 数据初始化，[子类可选实现]
     * 会在onCreate方法中initView方法之后被调用
     */
    open fun initData(savedInstanceState: Bundle?) {}

    /**
     * 提供ViewModelFactory
     * @return ViewModelProvider.Factory
     */
    open fun provideViewModelFactory(): ViewModelProvider.Factory {
        return ViewModelProvider.AndroidViewModelFactory(application);
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //系统版本不小于5.0 ,用于处理webView显示不完整的问题
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            WebView.enableSlowWholeDocumentDraw();
        }

        if (_useBinding) {
            mVDB = providerViewDataBinding()
            mVDB.lifecycleOwner = this
        } else {
            layoutId?.let { setContentView(it) }
        }

        mVM = providerViewModel()
        hideStatusBar()
        initView(savedInstanceState)
        bindEvent()
        initData(savedInstanceState)
    }

    protected fun hideStatusBar() {
        // 5.0以上系统状态栏透明
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            //白色SYSTEM_UI_FLAG_LAYOUT_STABLE、深色SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
            window.decorView.systemUiVisibility =
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
            window.statusBarColor = Color.TRANSPARENT
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        }
    }

    /**
     * 获取DataBinding
     */
    private fun providerViewDataBinding(): VDB {
        return DataBindingUtil.setContentView(this, layoutId!!)
    }

    /**
     * 获取ViewModel
     */
    private fun providerViewModel(): VM {
        //当继承关系较为复杂时需要遍历找到正确的class
        var clazz:Class<*> = javaClass
        while (clazz.genericSuperclass !is ParameterizedType && clazz.genericSuperclass is Class<*>){
            clazz = clazz.genericSuperclass as Class<*>
        }
        val genericSuperclass: ParameterizedType = clazz.genericSuperclass as ParameterizedType

        val actualTypeArguments: Array<Type> = genericSuperclass.actualTypeArguments
        val vmClass: Class<VM> = actualTypeArguments[1] as Class<VM>
        return ViewModelProvider(this, provideViewModelFactory()).get(vmClass)
    }

    /**
     * 设置状态栏颜色
     * @param color String
     */
    protected fun setStatusBarColor(color: String) {
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.statusBarColor = Color.parseColor(color)
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        if (newConfig.fontScale != 1.0f) {
            resources
        }
        super.onConfigurationChanged(newConfig)
    }

    override fun getResources(): Resources? {
        val res: Resources? = super.getResources()
        if (res != null) {
            val config: Configuration? = res.configuration
            if (config != null && config.fontScale != 1.0f) {
                config.fontScale = 1.0f
                res.updateConfiguration(config, res.getDisplayMetrics())
            }
        }
        return res
    }
}